<?php

namespace App\Models\video;

use App\Http\Config\ErrorCode;
use App\Library\TcScfUtil;
use App\Library\UpTools;
use Qcloud\Cos\Client;
use TencentCloud\Common\Credential;
use TencentCloud\Vod\V20180717\Models\AiContentReviewTaskInput;
use TencentCloud\Vod\V20180717\Models\ApplyUploadRequest;
use TencentCloud\Vod\V20180717\Models\CommitUploadRequest;
use TencentCloud\Vod\V20180717\Models\DeleteMediaRequest;
use TencentCloud\Vod\V20180717\Models\DescribeMediaInfosRequest;
use TencentCloud\Vod\V20180717\Models\DescribeTaskDetailRequest;
use TencentCloud\Vod\V20180717\Models\MediaProcessTaskInput;
use TencentCloud\Vod\V20180717\Models\ModifyMediaInfoRequest;
use TencentCloud\Vod\V20180717\Models\ProcessMediaRequest;
use TencentCloud\Vod\V20180717\VodClient;

// 云点播 api接口
class VodApis
{
    protected $returnData;
    protected $secretId;
    protected $secretKey;
    protected $region = 'ap-guangzhou';
    static $vodObject;
    protected $vodClient;
    protected $classId = 0; // 分类ID  看腾讯云 云点播的分类ID
    private $aiContentReviewId = 50; // 内容审核模板ID   https://console.cloud.tencent.com/vod/video-process/template/audit
    private $coverBySnapshotList = [['Definition' => 10, 'PositionType' => 'Time', 'PositionValue' => 0]]; // 指定时间点截图做封面   https://cloud.tencent.com/document/api/266/31773#CoverBySnapshotTaskInput
    private $transCodeList = [360 => 100010, 720 => 100030, 1080 => 100040, 1440 => 100070]; // 转码任务列表 从小排到大 https://cloud.tencent.com/document/api/266/31773#TranscodeTaskInput
    private $adaptiveDynamicStreamingList = [['Definition' => 10]]; // 自适应码流列表  https://cloud.tencent.com/document/api/266/31773#AdaptiveDynamicStreamingTaskInput

    public function __construct($secretId, $secretKey, $screenShot = 10, $vodClassId = 0)
    {
        require_once base_path() . '/vendor/tencentcloud-sdk-php/TCloudAutoLoader.php';
        require_once base_path() . '/vendor/cos-php-sdk/autoload.php';
        $this->returnData = ErrorCode::$admin_enum["success"];
        $this->secretId = $secretId;
        $this->secretKey = $secretKey;
        $this->classId = $this->createClass($vodClassId);
        $this->coverBySnapshotList[0]['Definition'] = $this->createSnapshotByTimeOffsetTemplate($screenShot);
    }

    public function createClass($vodClassId = 0){
        if(!$vodClassId) {
            $name = substr("up主-".CommonServer::getUrl('', false)."(".request()->mallData["id"].")", 0, 64);
            $data = TcScfUtil::getInstance($this->secretId, $this->secretKey, "vod")->vodCreateClass(['ClassName' => $name, 'ParentId' => -1]);
            if(!empty($data['data']['ClassId'])){
                $vodClassId = $data['data']['ClassId'];
                VideoSettingModel::doUpdate(['vod_class_id' => $vodClassId], ["mall_id" => request()->mallData["id"]]);
            }
        }
        return $vodClassId;
    }

    public function createSnapshotByTimeOffsetTemplate($screenShot = 0){
        if(!$screenShot || $screenShot == 10) {
            $name = substr("自定义-".CommonServer::getUrl('', false)."(".request()->mallData["id"].")", 0, 64);
            $data = TcScfUtil::getInstance($this->secretId, $this->secretKey, "vod")->vodCreateSnapshotByTimeOffsetTemplate([
                'Name' => $name, 'Width' => 750, 'Height' => 422, "Comment" => "16：9"
            ]);
            if(!empty($data['data']['Definition'])){
                $screenShot = $data['data']['Definition'];
                VideoSettingModel::doUpdate(['screen_shot' => $screenShot], ["mall_id" => request()->mallData["id"]]);
            }
        }
        return $screenShot;
    }

    /**
     * @return VodApis
     * @throws \Exception
     */
    public static function getInstance(){
        $param = func_get_args();
        if(empty($param)){
            static $settingData;
            if(empty($settingData))
                $settingData = VideoSettingModel::getFields("secret_id,secret_key,screen_shot,vod_class_id", ["mall_id" => request()->mallData["id"]]);
            if(empty($settingData["secretId"]) || empty($settingData["secretKey"])){
                throw new \Exception("腾讯云云点播访问密钥未配置");
            }
            $param[0] = $settingData["secretId"];
            $param[1] = $settingData["secretKey"];
            $param[2] = $settingData["screenShot"];
            $param[3] = $settingData["vodClassId"];
        }
        $md5 = md5(implode("", $param));
        if(empty(self::$vodObject[$md5])){
            self::$vodObject[$md5] = new self($param[0], $param[1], $param[2], $param[3]);
        }
        return self::$vodObject[$md5];
    }

    public function getClient(){
        if(empty($this->vodClient)) {
            $this->vodClient = new VodClient(new Credential($this->secretId, $this->secretKey), $this->region);
        }
        return $this->vodClient;
    }

    // 上传媒体  https://cloud.tencent.com/document/product/266/31767
    public function uploadMediaFile($uploadList){
        try {
            if(!in_array(strtoupper($uploadList["fileType"]), UpTools::vodMediaType())){
                $this->returnData = ErrorCode::$admin_enum["fail"];
                $this->returnData["msg"] = "云点播不支持上传该文件";
            }else {
                $vodClient = $this->getClient();
                $request = new ApplyUploadRequest();
                $request->deserialize(["MediaType" => $uploadList["fileType"], "MediaName" => "未命名", "ClassId" => $this->classId]);
                $request->MediaFilePath = $uploadList["filePath"];
                // 申请上传
                $response = $vodClient->ApplyUpload($request);
                $cosCredential = array();
                if (isset($response->TempCertificate)) {
                    $certificate = $response->TempCertificate;
                    $cosCredential['secretId'] = $certificate->SecretId;
                    $cosCredential['secretKey'] = $certificate->SecretKey;
                    $cosCredential['token'] = $certificate->Token;
                } else {
                    $cosCredential['secretId'] = $this->secretId;
                    $cosCredential['secretKey'] = $this->secretKey;
                }
                $cosClient = new Client(array('region' => $response->StorageRegion, 'credentials' => $cosCredential));
                if (!empty($response->MediaStoragePath)) { // 媒体文件
                    $cosClient->Upload($response->StorageBucket, $response->MediaStoragePath, fopen($uploadList["filePath"], 'rb'));
                }
                // 确认上传
                $request = new CommitUploadRequest();
                $request->VodSessionKey = $response->VodSessionKey;
                $response = $vodClient->CommitUpload($request);
                $this->returnData["data"] = $response->serialize();
            }
        } catch (\Exception $e) {
            $this->returnData = ErrorCode::$admin_enum["fail"];
            $this->returnData["msg"] = $e->getMessage();
        }
        return $this->returnData;
    }

    public function handleMediaFile($vid, $resolution = 0){
        try {
            // 视频处理
            $mediaProcessInput = new MediaProcessTaskInput();
            $mediaProcessInput->setCoverBySnapshotTaskSet($this->coverBySnapshotList); // 封面
            foreach ($this->transCodeList as $k => $v){
                if($resolution && $resolution < $k){
                    continue;
                }
                $transCodeList[] = ["Definition" => $v];
            }
            if(empty($transCodeList)){
                $transCodeList[] = ["Definition" => current($this->transCodeList)];
            }
            if(count($transCodeList) < 2){
                $transCodeList[] = ["Definition" => next($this->transCodeList)];
            }
            $mediaProcessInput->setTranscodeTaskSet($transCodeList); // 转码列表
            $mediaProcessInput->setAdaptiveDynamicStreamingTaskSet($this->adaptiveDynamicStreamingList); // 转自适应码流
            $request = new ProcessMediaRequest();
            $request->setMediaProcessTask($mediaProcessInput); // 视频处理类型任务列表
//        $aiContentReviewInput = new AiContentReviewTaskInput();
//        $aiContentReviewInput->Definition = $this->aiContentReviewId;
//        $request->setAiContentReviewTask($aiContentReviewInput); // 视频内容审核类型任务
            $request->setFileId($vid);
            $vodClient = $this->getClient();
            $response = $vodClient->ProcessMedia($request);
            $value = $response->serialize();
            if (!empty($value)) {
                DataCacheModel::saveCache(["key" => "uploadMedia_{$vid}", "value" => $value, "time" => 43200]);
                return true;
            } else {
                $this->deleteMedia($vid);
            }
        }catch (\Exception $e){
            UpTools::writeLog($e->getTraceAsString().$e->getMessage().var_export($request, true), "handleMediaFile.txt");
            $this->deleteMedia($vid);
        }
        return false;
    }

    public function handleMediaFileByAudio($vid){
        try {
            // 视频处理
            $mediaProcessInput = new MediaProcessTaskInput();
            $mediaProcessInput->setCoverBySnapshotTaskSet($this->coverBySnapshotList); // 封面
            $request = new ProcessMediaRequest();
            $request->setMediaProcessTask($mediaProcessInput); // 视频处理类型任务列表
            $request->setFileId($vid);
            $vodClient = $this->getClient();
            $response = $vodClient->ProcessMedia($request);
            $value = $response->serialize();
            if (!empty($value)) {
                DataCacheModel::saveCache(["key" => "uploadMedia_{$vid}", "value" => $value, "time" => 43200]);
                return true;
            } else {
                $this->deleteMedia($vid);
            }
        }catch (\Exception $e){
            UpTools::writeLog($e->getTraceAsString().$e->getMessage().var_export($request, true), "handleMediaFileByAudio.txt");
            $this->deleteMedia($vid);
        }
        return false;
    }

    // 修改媒体文件信息 https://cloud.tencent.com/document/product/266/31762
    public function modifyMediaInfo($fileId, $params){
        $request = new ModifyMediaInfoRequest();
        $requestParams = ["Name" => $params["title"], "FileId" => $fileId, 'ClassId' => $this->classId];
        if(mb_strlen($requestParams["Name"]) > 64){
            $requestParams["Name"] = mb_substr($requestParams["Name"], 0, 64);
        }
        if(!empty($params["desc"])){
            $requestParams['Description'] = $params["desc"];
            if(mb_strlen($requestParams["Description"]) > 128){
                $requestParams["Description"] = mb_substr($requestParams["Description"], 0, 64);
            }
        }
        if(!empty($params["coverImgId"])){
            $requestParams['CoverData'] = @base64_encode(@file_get_contents(UpTools::processingPictures($params["coverImgId"])));
        }
        $request->deserialize($requestParams);
        $response = $this->getClient()->ModifyMediaInfo($request);
        $this->returnData["data"] = $response->serialize();
        return $this->returnData;
    }

    // 获取媒体详细信息  https://cloud.tencent.com/document/product/266/31763
    public function getDescribeMediaInfos($fileId){
        $request = new DescribeMediaInfosRequest();
        $request->setFileIds([$fileId]);
        $request->setFilters(["basicInfo", "transcodeInfo", "adaptiveDynamicStreamingInfo"]);
        $response = $this->getClient()->DescribeMediaInfos($request);
        $this->returnData["data"] = $response->serialize();
        return $this->returnData;
    }

    // 删除媒体   https://cloud.tencent.com/document/product/266/31764
    public function deleteMedia($fileId){
        $request = new DeleteMediaRequest();
        $request->setFileId($fileId);
        $response = $this->getClient()->DeleteMedia($request);
        $this->returnData["data"] = $response->serialize();
        return $this->returnData;
    }

    // 查看任务流的结果
    public function describeTaskDetail($taskId){
        $request = new DescribeTaskDetailRequest();
        $request->setTaskId($taskId);
        $response = $this->getClient()->DescribeTaskDetail($request);
        $this->returnData["data"] = $response->serialize();
        return $this->returnData;
    }
}
